package com.simple.question;

import java.util.Date;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
import java.io.Serializable;
import java.util.logging.Logger;

public abstract class CommonTree<T extends CommonTree<T>> implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	private static final Logger logger = Logger.getLogger("CommonTree");
	
	//为了分页加的属性
	private static final int DEAFALT_PAGE_NO = 1;
	private static final int DEAFALT_PAGE_SIZE = 10;

	private int pageNo = DEAFALT_PAGE_NO;

	private int pageSize = DEAFALT_PAGE_SIZE;
	
	/** 节点移动时，源节点和目标结点的相对位置  1:inner;2:previous;3:next;4:outer */
	public static final int MOVE_TYPE_INNER = 1;
	
	public static final int MOVE_TYPE_PREV = 2;
	
	public static final int MOVE_TYPE_NEXT = 3;
	
	public static final int MOVE_TYPE_OUTER = 4;
	
	private int start;
	
	//原来 的属性
	protected long id;
	
	protected String name;
	
	protected long pId;
	
	protected String no;
	
	protected boolean checked = false;
	
	protected boolean isLeaf = true;
	
	protected String dcrp;

	protected long creator;

	protected Date crtDate;

	protected Date modifyDate;
	
	protected long modifier;
	
	protected Date modifyDateInP;;
	
	protected T parent;
	
	protected List<T> children;
	
	/** 临时变量：知识点节点移动的变量 */
	private int moveType;
	private Long targetId;
	private List<Long> sourceIds;
	//2014-12-16 临时变量:符号
	private String symbol;
	
	/**
	 * 获取默认根节点
	 * @return
	 */
	public T getDefRootNode(Class<T> cls){
		T instance = null;
		try {
			instance = cls.newInstance();
			instance.setId(-1);
			instance.setpId(-100);
			instance.setName("根节点");
			instance.setNo("");
			instance.setDcrp("root node");
		} catch (InstantiationException e) {
		} catch (IllegalAccessException e) {
		}
		return instance;
	}
	
	public List<T> sortListByTree(List<T> nodes){
		if(null==nodes || nodes.size()==0){
			return null;
		}
		List<T> treeNodes = new ArrayList<T>();
		try{
		List<T> children = null;
		T cur = null;
		T next = null;
		T parent = null;
		int nexti = 0;
		int size = nodes.size();
		int curLen = 0;
		int nextLen = 0;
		
		int firstLen = 0;
		Map<Long,T> nodeMap = new HashMap<Long,T>();
		for(int i=0;i<size;i++){
			nexti = i == size - 1 ? (size - 1) : (i + 1);
			//保留多个兄弟节点的父节点
			if (null != next) {
				parent = next.getParent();
			}
			cur = nodes.get(i);
			nodeMap.put(cur.getId(), cur);
			next = nodes.get(nexti);
			curLen = cur.getNo().length();
			nextLen = next.getNo().length(); 
			if(i==0){	
				firstLen = curLen;
			}
			if(firstLen == curLen){
				treeNodes.add(cur);
			}
			
			//有子节点
			if (curLen < nextLen) {
				children = new ArrayList<T>();
				children.add(next);
				next.setParent(cur);
				cur.setChildren(children);
			}
			//有兄弟节点，并确保最后一个节点不重复比较
			else if (curLen == nextLen && cur.getId() != next.getId()) {
				next.setParent(parent);
				parent.getChildren().add(next);
			}
			//当前是叶子节点，下一个是另一个根节点
			else if (curLen > nextLen) {
				T tmpParent = nodeMap.get(next.getpId());
				if(null==tmpParent){
					parent = tmpParent;
				}else{
					tmpParent.getChildren().add(next);
					next.setParent(tmpParent);
					parent = next;
				}
			}
		}
		}catch(Exception e){
		}
		return treeNodes;
	}
	
	/**
	 * 获取该节点的路径列表
	 * @param nodes
	 * @return
	 */
	public Map<Long,String> getTreePath(List<T> nodes){
		if(null==nodes || nodes.size()==0){
			return null;
		}
	
		Map<Long,String> idPathMap = new HashMap<Long,String>();
		Map<String,String> noNameMap = new HashMap<String,String>();
		try{
			T cur = null;
			int size = nodes.size();
			int noLength = 0;
			int interval = 0;
			String no = null;
			String path = null;
			String tmp = null;
			
			for(int i=0;i<size;i++){
				cur = nodes.get(i);
				no = cur.getNo();
				
				if(cur.id == -1 || cur.pId == -100){
					noLength = no.length();
				}
				
				interval = no.length() / noLength;
				noNameMap.put(no, cur.getName());
				
				path = null;
				for (int j = 0; j < interval - 1; j++) {
					tmp = noNameMap.get(no.substring(j, j + noLength));
					if(null != tmp){
						path = (null == path ? "" : path);
						path += "/" + tmp;
					}
				}
				idPathMap.put(cur.getId(), (path == null ? "/" : (path + "/")) + cur.getName());
			}
		}catch(Exception e){
			//logger.error("CommonTree getParentPath() error:",e);
		}
		return idPathMap;
	}
	
	
	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public long getpId() {
		return pId;
	}

	public void setpId(long pId) {
		this.pId = pId;
	}

	public String getNo() {
		return no;
	}

	public void setNo(String no) {
		this.no = no;
	}
	
	public boolean isChecked() {
		return checked;
	}

	public void setChecked(boolean checked) {
		this.checked = checked;
	}

	public boolean isLeaf() {
		return isLeaf;
	}

	public void setLeaf(boolean isLeaf) {
		this.isLeaf = isLeaf;
	}
	
	public String getDcrp() {
		return dcrp;
	}

	public void setDcrp(String dcrp) {
		this.dcrp = dcrp;
	}
	
	public long getCreator() {
		return creator;
	}

	public void setCreator(long creator) {
		this.creator = creator;
	}

	public Date getCrtDate() {
		return crtDate;
	}

	public void setCrtDate(Date crtDate) {
		this.crtDate = crtDate;
	}
	
	public Date getModifyDateInP() {
		return modifyDateInP;
	}

	public void setModifyDateInP(Date modifyDateInP) {
		this.modifyDateInP = modifyDateInP;
	}

	public T getParent() {
		return parent;
	}

	public void setParent(T parent) {
		this.parent = parent;
	}

	public List<T> getChildren() {
		return children;
	}

	public void setChildren(List<T> children) {
		this.children = children;
	}
	
	public Date getModifyDate() {
		return modifyDate;
	}

	public void setModifyDate(Date modifyDate) {
		this.modifyDate = modifyDate;
	}

	public int getPageNo() {
		return pageNo;
	}

	public void setPageNo(int pageNo) {
		this.pageNo = pageNo;
	}

	public int getPageSize() {
		return pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public int getStart() {
		return start;
	}

	public void setStart(int start) {
		this.start = start;
	}
	
	public int getMoveType() {
		return moveType;
	}

	public void setMoveType(int moveType) {
		this.moveType = moveType;
	}

	public Long getTargetId() {
		return targetId;
	}

	public void setTargetId(Long targetId) {
		this.targetId = targetId;
	}

	public List<Long> getSourceIds() {
		return sourceIds;
	}

	public void setSourceIds(List<Long> sourceIds) {
		this.sourceIds = sourceIds;
	}

	public String getSymbol() {
		return symbol;
	}

	public void setSymbol(String symbol) {
		this.symbol = symbol;
	}

	public long getModifier() {
		return modifier;
	}

	public void setModifier(long modifier) {
		this.modifier = modifier;
	}
}
